#include <libsoup/soup.h>
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
#include <string.h>
#include <sys/stat.h>
#include <expat.h>

#define DD(...) fprintf(stdout, __VA_ARGS__)
#ifndef PWA_UPLOADER_DATA_PATH
#define PWA_UPLOADER_DATA_PATH "./data"
#endif

#define PWA_UPLOADER_AGENT     "PWA-Uploader"
#define PWA_UPLOADER_CFG       ".pwa-uploader.ini"

#define PWA_DATA_URL "http://picasaweb.google.com/data/feed/api/user/"
#define GOOGLE_ACCOUNT_URL "http://www.google.com/accounts/"
#define PICASA_AUTH_URL  "https://www.google.com/accounts/ClientLogin"
#define PICASA_SERVICE_NAME "lh2"
#define PICASA_AUTH_MIMETYPE "application/x-www-form-urlencoded"
#define MYGROUP "PICASA"
#define EF fprintf(stdout, "END of %s\n", __func__)

typedef enum {
  PWA_UPLOADER_STA_0,
  PWA_UPLOADER_STA_LOGIN,
  PWA_UPLOADER_STA_LOGINOK,
  PWA_UPLOADER_STA_LOGINERR,
  PWA_UPLOADER_STA_CAPTCHAREQUIRED,
  PWA_UPLOADER_STA_GOTCAPTCHA,
  PWA_UPLOADER_STA_UPLOADING,
  PWA_UPLOADER_STA_IDLE
} pwa_uploader_sta_t;

typedef struct _pwa_account pwa_account_t;
typedef struct {
  GtkStatusIcon *icon;
  GdkRectangle area;
  GtkOrientation orientation;

  GtkWidget *aboutdlg, *logindlg, *notifydlg;
  GtkWidget *imagebrowser, *uploadmanager;
  GtkWidget *rpchkbtn, *alchkbtn;
  GtkWidget *ib_forwardbtn, *as_uploadbtn;
  GKeyFile *kf;

  GtkWidget *preview, *filesize, *imagesize;

  GtkWidget *browser_page, *albums_page;
  GtkWidget *as_widgetset, *as_albums, *as_title, *as_description, *as_date, *as_address, *as_accessmode, *as_backbtn;
  pwa_account_t *account;
} pwa_uploader_ui_t;

struct _pwa_account{
  SoupSession *session;
  pwa_uploader_sta_t sta;

  gchar *password, *username, *token;
  gchar *error, *captcha_token;
  GdkPixbuf *captcha_pixbuf;

  pwa_uploader_ui_t *ui;
  GSList *albums;
  XML_Parser parser, ca_parser;
  GtkTreeModel *model;
  GSList *tasks;
};

typedef struct {
  gchar *id, *name;
  gchar *thumbnail;
  gchar *numphotos;
  gchar *address;
  gchar *access;
  gchar *title, *description, *date;
} pwa_album_t;

typedef struct {
  GSList *urilist;
  pwa_album_t *album;
} pwa_upload_task_t;
 
enum {
  PWA_TITLE_COL = 0,
  PWA_ALBUM_COL,
  PWA_NUM_COL
};

static const char *curr_name = NULL;
static pwa_album_t *curr_album = NULL;
static void pwa_fetch_albums(pwa_account_t *account);
static void pwa_create_album(pwa_account_t *account, gchar *title, gchar *description, gchar *address, gchar *access);
static void pwa_upload_photo(pwa_account_t *account, pwa_album_t *album, gchar *file);

static void format_size(int size, gchar *sizebuf) {
  if(size > 1024) {
    if(size > 1024 * 1024) {
      g_snprintf(sizebuf, 256, "%.2f MB", size/(1024*1024.0));
    } else {
      g_snprintf(sizebuf, 256, "%.2f KB", size/1024.0);
    }
  } else {
    g_snprintf(sizebuf, 256, " %.2f KB", size/1024.0);
  }
}

static void update_preview_cb(GtkFileChooser *chooser, gpointer data) {
  GtkWidget *preview = NULL;
  pwa_uploader_ui_t *ui = (pwa_uploader_ui_t *)data;
  gchar *filename = NULL;
  GdkPixbuf *pixbuf = NULL;
  struct stat buf;

  preview = ui->preview;
  filename = gtk_file_chooser_get_preview_filename (chooser);
  if(! filename) return;

  stat(filename, &buf);
  pixbuf = gdk_pixbuf_new_from_file_at_scale(filename, 256, 256, TRUE, NULL);
  //DD("update-preview event, filename = %s, pixbuf = %x, size = %d\n", filename, pixbuf, buf.st_size);

  if(pixbuf) {
    gchar msg[1024] = {0}, sizebuf[256] = {0};
    gint width, height;

    gtk_image_set_from_pixbuf(GTK_IMAGE(preview), pixbuf);
    g_object_unref(pixbuf);
    format_size(buf.st_size, sizebuf);
    snprintf(msg, 1024, "<b>File Size</b>: %s", sizebuf);
    gtk_label_set_markup(GTK_LABEL(ui->filesize), msg);
    bzero(msg, 1024);
    pixbuf = gdk_pixbuf_new_from_file(filename, NULL);
    gdk_pixbuf_get_file_info(filename, &width, &height);
    g_snprintf(msg, 1024, "<b>Image Size</b>: %d x %d", width, height);
    g_object_unref(pixbuf);
    gtk_label_set_markup(GTK_LABEL(ui->imagesize), msg);
  }
  gtk_file_chooser_set_preview_widget_active (chooser, pixbuf != NULL);
  gtk_widget_show(ui->preview);
  gtk_widget_show(ui->filesize);
  gtk_widget_show(ui->imagesize);
  g_free(filename);
}

static void selection_changed_cb(GtkFileChooser *chooser, gpointer data) {
  DD("selection-changed event\n");
}

static gboolean file_filter_cb(const GtkFileFilterInfo *info, gpointer data) {
  if(info && strcmp(info->mime_type, "image/jpeg") == 0)
    return TRUE;

  return FALSE;
}

static gboolean _is_separator(GtkTreeModel *model,GtkTreeIter  *iter, gpointer data) {
  GValue title = {0, }, album = {0, };
  gboolean ret;

  //DD("model = %x, iter = %x\n", model, iter);
  gtk_tree_model_get_value(model, iter, PWA_TITLE_COL, &title);
  //gtk_tree_model_get_value(model, iter, PWA_TITLE_COL, &title);
  //DD("is_separator.title = %s\n", g_value_get_string(&title));

  ret = g_value_get_string(&title) == NULL;
  g_value_unset(&title);

  return ret;
}

void albums_selection_changed_cb (GtkComboBox *button, gpointer data) {
  GtkTreeIter iter;
  GValue album = {0, }, title = {0, };
  GtkTreeModel *model = NULL;
  gchar buf[128] = {0};
  time_t t;
  const gchar *szurl = NULL, *sztitle = NULL;
  pwa_album_t *ptr = NULL;
  pwa_uploader_ui_t *ui = (pwa_uploader_ui_t *)data;

  if(gtk_combo_box_get_active_iter(button, &iter)) {
    model = gtk_combo_box_get_model(button);
    gtk_tree_model_get_value(model, &iter, PWA_TITLE_COL, &title);
    gtk_tree_model_get_value(model, &iter, PWA_ALBUM_COL, &album);
    //DEBUG("GtkComboBox changed event, path = %s\n", gtk_tree_path_to_string(gtk_tree_model_get_path(model, &iter)));

    ptr = g_value_get_pointer(&album);
    if(ptr) {
      t = atol(ptr->date);
      strftime(buf, 128, "%F", localtime(&t));

      gtk_entry_set_text(GTK_ENTRY(ui->as_title), ptr->title);
      gtk_entry_set_text(GTK_ENTRY(ui->as_date), buf);
      gtk_entry_set_text(GTK_ENTRY(ui->as_address), ptr->address);

      if(ptr->description) {
        GtkTextBuffer *textbuf = gtk_text_buffer_new(NULL);
        gtk_text_buffer_set_text(textbuf, ptr->description, strlen(ptr->description));
        gtk_text_view_set_buffer(GTK_TEXT_VIEW(ui->as_description), textbuf);
        g_object_unref(textbuf);
      } else {
        gtk_text_view_set_buffer(GTK_TEXT_VIEW(ui->as_description), NULL);
      }
      if(strcmp(ptr->access, "public") == 0) {
        gtk_combo_box_set_active (GTK_COMBO_BOX(ui->as_accessmode), 0);
      } else if(strcmp(ptr->access, "private") == 0) {
        gtk_combo_box_set_active (GTK_COMBO_BOX(ui->as_accessmode), 1);
      } else {
        gtk_combo_box_set_active (GTK_COMBO_BOX(ui->as_accessmode), 2);
      }
      gtk_widget_set_sensitive(ui->as_widgetset, FALSE);
    } else {
      GtkTextBuffer *textbuf = gtk_text_buffer_new(NULL);
      t = time(NULL);
      strftime(buf, 128, "%F", localtime(&t));

      gtk_entry_set_text(GTK_ENTRY(ui->as_title), "");
      gtk_entry_set_text(GTK_ENTRY(ui->as_date), buf);
      gtk_entry_set_text(GTK_ENTRY(ui->as_address), "");

      gtk_text_buffer_set_text(textbuf, "", strlen(""));
      gtk_text_view_set_buffer(GTK_TEXT_VIEW(ui->as_description), textbuf);
      g_object_unref(textbuf);

      gtk_combo_box_set_active (GTK_COMBO_BOX(ui->as_accessmode), 0);

      gtk_widget_set_sensitive(ui->as_widgetset, TRUE);
    }

    g_value_unset(&album);
    g_value_unset(&title);
  }
}

static GtkWidget *create_albums_selection_page(pwa_uploader_ui_t *ui) {
  GtkWidget *hbox = NULL, *hvbox = NULL, *hvvbox = NULL;
  GtkWidget *_hbox = NULL, *_vbox = NULL,  *entry = NULL, *label = NULL;

  hbox = gtk_hbox_new(TRUE, 2);
  hvbox = gtk_vbox_new(TRUE, 2);

  hvvbox = gtk_vbox_new(FALSE, 8);
  {
    _vbox = gtk_vbox_new(FALSE, 2);
    {
      _hbox = gtk_hbox_new(FALSE, 2);
      label = gtk_label_new("");
      gtk_label_set_markup(GTK_LABEL(label), "<span size='medium'>Title:</span>");
      gtk_box_pack_start(GTK_BOX(_hbox), label, FALSE, TRUE, 0);
      gtk_box_pack_start(GTK_BOX(_vbox), _hbox, FALSE, TRUE, 0);
    }
    ui->as_title = entry = gtk_entry_new();
    gtk_box_pack_start(GTK_BOX(_vbox), entry, FALSE, TRUE, 0);
    gtk_box_pack_start(GTK_BOX(hvvbox), _vbox, FALSE, TRUE, 0);
  }

  {
    _vbox = gtk_vbox_new(FALSE, 2);
    {
      _hbox = gtk_hbox_new(FALSE, 2);
      label = gtk_label_new("");
      gtk_label_set_markup(GTK_LABEL(label), "<span size='medium'>Date:</span>");
      gtk_box_pack_start(GTK_BOX(_hbox), label, FALSE, TRUE, 0);
      gtk_box_pack_start(GTK_BOX(_vbox), _hbox, FALSE, TRUE, 0);
    }
    ui->as_date = entry = gtk_entry_new();
    gtk_box_pack_start(GTK_BOX(_vbox), entry, FALSE, TRUE, 0);
    gtk_box_pack_start(GTK_BOX(hvvbox), _vbox, FALSE, TRUE, 0);
  }

  {
    _vbox = gtk_vbox_new(FALSE, 2);
    {
      _hbox = gtk_hbox_new(FALSE, 2);
      label = gtk_label_new("");
      gtk_label_set_markup(GTK_LABEL(label), "<span size='medium'>Description(Optional):</span>");
      gtk_box_pack_start(GTK_BOX(_hbox), label, FALSE, TRUE, 0);
      gtk_box_pack_start(GTK_BOX(_vbox), _hbox, FALSE, TRUE, 0);
    }
    {
      GtkWidget *sw = NULL;
      sw = gtk_scrolled_window_new(NULL, NULL);
      ui->as_description = entry = gtk_text_view_new();
      gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(entry), GTK_WRAP_WORD);
      gtk_container_add(GTK_CONTAINER(sw), entry);
      gtk_widget_set_size_request(GTK_WIDGET(sw), 420, 120);
      gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_ETCHED_IN);
      gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
      gtk_box_pack_start(GTK_BOX(_vbox), sw, FALSE, TRUE, 0);
    }
    gtk_box_pack_start(GTK_BOX(hvvbox), _vbox, FALSE, TRUE, 0);
  }

  {
    _vbox = gtk_vbox_new(FALSE, 2);
    {
      _hbox = gtk_hbox_new(FALSE, 2);
      label = gtk_label_new("");
      gtk_label_set_markup(GTK_LABEL(label), "<span size='medium'>Address:</span>");
      gtk_box_pack_start(GTK_BOX(_hbox), label, FALSE, TRUE, 0);
      gtk_box_pack_start(GTK_BOX(_vbox), _hbox, FALSE, TRUE, 0);
    }
    ui->as_address = entry = gtk_entry_new();
    gtk_box_pack_start(GTK_BOX(_vbox), entry, FALSE, TRUE, 0);

    gtk_box_pack_start(GTK_BOX(hvvbox), _vbox, FALSE, TRUE, 0);
  }

  {
    _vbox = gtk_vbox_new(FALSE, 2);
    {
      _hbox = gtk_hbox_new(FALSE, 2);
      label = gtk_label_new("");
      gtk_label_set_markup(GTK_LABEL(label), "<span size='medium'>Access Mode:</span>");
      gtk_box_pack_start(GTK_BOX(_hbox), label, FALSE, TRUE, 0);
      gtk_box_pack_start(GTK_BOX(_vbox), _hbox, FALSE, TRUE, 0);
    }
    {
      GtkWidget *combo = NULL;
      ui->as_accessmode = combo =  gtk_combo_box_new_text();
      gtk_combo_box_append_text(GTK_COMBO_BOX(combo), "Public");
      gtk_combo_box_append_text(GTK_COMBO_BOX(combo), "Private");
      gtk_combo_box_append_text(GTK_COMBO_BOX(combo), "Public to friends");
      gtk_combo_box_set_active (GTK_COMBO_BOX(combo), 0);
      gtk_box_pack_start(GTK_BOX(_vbox), combo, FALSE, TRUE, 0);
    }
    gtk_box_pack_start(GTK_BOX(hvvbox), _vbox, FALSE, TRUE, 0);
  }

  {
    GtkWidget *combo = NULL;
    GtkCellRenderer *renderer = NULL;

    _vbox = gtk_vbox_new(FALSE, 16);
    ui->as_albums = combo = gtk_combo_box_new();
    renderer = gtk_cell_renderer_text_new ();
    gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), renderer, TRUE);
    gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo), renderer, "text", PWA_TITLE_COL, NULL);
    gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (combo), _is_separator, NULL, NULL);
    g_signal_connect(G_OBJECT(combo), "changed", G_CALLBACK(albums_selection_changed_cb), ui);

    //gtk_combo_box_append_text(GTK_COMBO_BOX(ui->as_albums), "New Album");
    gtk_box_pack_start(GTK_BOX(_vbox), combo, FALSE, TRUE, 0);
    gtk_box_pack_start(GTK_BOX(_vbox), hvvbox, FALSE, FALSE, 0);

    gtk_box_pack_start(GTK_BOX(hvbox), _vbox, FALSE, FALSE, 0);
    ui->as_widgetset = hvvbox;
    //gtk_widget_set_sensitive(ui->as_widgetset, FALSE);
  }
  gtk_box_pack_start(GTK_BOX(hbox), hvbox, FALSE, FALSE, 0);

  ui->albums_page = hbox;
  return hbox;
}

static GtkWidget *create_image_browser_page(pwa_uploader_ui_t *ui) {
  GtkWidget *chooser = NULL;
  GtkFileFilter *ff = NULL;
  GtkWidget *vbox = NULL, *vhbox = NULL;

  chooser = gtk_file_chooser_widget_new(GTK_FILE_CHOOSER_ACTION_OPEN);
  ff = gtk_file_filter_new();
  gtk_file_filter_add_custom(ff, GTK_FILE_FILTER_FILENAME|GTK_FILE_FILTER_MIME_TYPE, file_filter_cb, NULL, NULL);
  //g_signal_connect(G_OBJECT(chooser), "selection-changed", G_CALLBACK(selection_changed_cb), NULL);
  g_signal_connect(G_OBJECT(chooser), "update-preview", G_CALLBACK(update_preview_cb), ui);
  gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(chooser), ff);
  gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(chooser), TRUE);
  gtk_file_chooser_set_use_preview_label(GTK_FILE_CHOOSER(chooser), FALSE);

  vbox = gtk_vbox_new(FALSE, 0);
  ui->preview = gtk_image_new();
  gtk_box_pack_start(GTK_BOX(vbox), ui->preview, FALSE, TRUE, 6);

  vhbox = gtk_hbox_new(FALSE, 2);
  ui->filesize = gtk_label_new("");
  gtk_box_pack_start(GTK_BOX(vhbox), ui->filesize, FALSE, TRUE, 2);
  gtk_box_pack_start(GTK_BOX(vbox), vhbox, FALSE, TRUE, 1);

  vhbox = gtk_hbox_new(FALSE, 2);
  ui->imagesize = gtk_label_new("");
  gtk_box_pack_start(GTK_BOX(vhbox), ui->imagesize, FALSE, TRUE, 2);
  gtk_box_pack_start(GTK_BOX(vbox), vhbox, FALSE, TRUE, 1);

  gtk_widget_show_all(vbox);

  gtk_file_chooser_set_preview_widget (GTK_FILE_CHOOSER(chooser), vbox);
  gtk_widget_show_all(chooser);

  ui->browser_page = chooser;
  return chooser;
}

static void cancel_image_browser(GtkWidget *widget, gpointer data) {
  pwa_uploader_ui_t *ui = (pwa_uploader_ui_t *)data;

  gtk_widget_destroy(ui->imagebrowser);
  ui->imagebrowser = NULL;
}

static void albums_upload_cb(GtkWidget *widget, gpointer data) {
  pwa_uploader_ui_t *ui = (pwa_uploader_ui_t *)data;
  gchar *title = NULL, *description = NULL, *address = NULL, *access = "public";
  GtkTextIter si, ei;
  GtkTextBuffer *buf;

  title = gtk_entry_get_text(GTK_ENTRY(ui->as_title));
  address = gtk_entry_get_text(GTK_ENTRY(ui->as_address));

  buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(ui->as_description));
  gtk_text_buffer_get_start_iter(buf, &si);
  gtk_text_buffer_get_end_iter(buf, &ei);
  description = gtk_text_buffer_get_text(buf, &si, &ei, TRUE);
  //DD("title = %s, address = %s, description = %s\n", title, address, description);
  //pwa_create_album(ui->account, title, description, address, "public");
  //http://picasaweb.google.com/data/feed/api/user/pwa.uploader/albumid/5335606660338215121
  DD("upload photo to curr_album = %x, title = %s\n", curr_album, curr_album->title);
  pwa_upload_photo(ui->account, curr_album, "/home/user/photos/IMG_0709.jpg");
  //gtk_widget_show(ui->browser_page);
  //gtk_widget_hide(ui->albums_page);
  //gtk_widget_hide(ui->as_backbtn);
}

static void goback_image_browser(GtkWidget *widget, gpointer data) {
  pwa_uploader_ui_t *ui = (pwa_uploader_ui_t *)data;

  gtk_widget_show(ui->ib_forwardbtn);
  gtk_widget_show(ui->browser_page);
  gtk_widget_hide(ui->albums_page);
  gtk_widget_hide(ui->as_backbtn);
  gtk_widget_hide(ui->as_uploadbtn);
}

static void forward_image_browser(GtkWidget *widget, gpointer data) {
  pwa_uploader_ui_t *ui = (pwa_uploader_ui_t *)data;

  if(gtk_combo_box_get_model(GTK_COMBO_BOX(ui->as_albums)) == NULL) {
    gtk_combo_box_set_model(GTK_COMBO_BOX(ui->as_albums), ui->account->model);
    gtk_combo_box_set_active(GTK_COMBO_BOX (ui->as_albums), 0);
  }

  gtk_widget_hide(ui->ib_forwardbtn);
  gtk_widget_hide(ui->browser_page);
  gtk_widget_show(ui->albums_page);
  gtk_widget_show(ui->as_backbtn);
  gtk_widget_show(ui->as_uploadbtn);
}

static gboolean close_image_browser(GtkWidget *widget, GdkEvent *event, gpointer data) {
  pwa_uploader_ui_t *ui = (pwa_uploader_ui_t *)data;

  gtk_widget_destroy(ui->imagebrowser);
  ui->imagebrowser = NULL;
  return TRUE;
}

static void create_image_browser(pwa_uploader_ui_t *ui) {
  GtkWidget *vbox = NULL, *vhbox = NULL, *vhhbox = NULL;
  GtkWidget *btn = NULL;

  ui->imagebrowser = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_window_set_title(GTK_WINDOW(ui->imagebrowser), "Smart Browser");
  gtk_window_set_modal(GTK_WINDOW(ui->imagebrowser), TRUE);
  gtk_window_set_position(GTK_WINDOW(ui->imagebrowser), GTK_WIN_POS_CENTER_ALWAYS);
  gtk_window_maximize(GTK_WINDOW(ui->imagebrowser));
  gtk_container_set_border_width(GTK_CONTAINER(ui->imagebrowser), 8);

  vbox = gtk_vbox_new(FALSE, 2);

  gtk_box_pack_start(GTK_BOX(vbox), create_image_browser_page(ui), TRUE, TRUE, 2);
  gtk_box_pack_start(GTK_BOX(vbox), create_albums_selection_page(ui), TRUE, TRUE, 2);
  gtk_box_pack_start(GTK_BOX(vbox), gtk_hseparator_new(), FALSE, TRUE, 6);

  vhbox = gtk_hbox_new(FALSE, 0);
  vhhbox = gtk_hbox_new(TRUE, 8);
  btn = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
  g_signal_connect(G_OBJECT(btn), "clicked", G_CALLBACK(cancel_image_browser), ui);
  gtk_box_pack_start(GTK_BOX(vhhbox), btn, FALSE, TRUE, 0);
  ui->as_backbtn = btn = gtk_button_new_from_stock(GTK_STOCK_GO_BACK);
  g_signal_connect(G_OBJECT(btn), "clicked", G_CALLBACK(goback_image_browser), ui);
  gtk_box_pack_start(GTK_BOX(vhhbox), btn, FALSE, TRUE, 0);
  ui->as_uploadbtn = btn = gtk_button_new();
  gtk_button_set_label(GTK_BUTTON(btn), "Upload");
  gtk_button_set_image(GTK_BUTTON(btn), gtk_image_new_from_stock(GTK_STOCK_GO_UP, GTK_ICON_SIZE_BUTTON));
  g_signal_connect(G_OBJECT(btn), "clicked", G_CALLBACK(albums_upload_cb), ui);
  gtk_box_pack_start(GTK_BOX(vhhbox), btn, FALSE, TRUE, 0);

  ui->ib_forwardbtn = btn = gtk_button_new_from_stock(GTK_STOCK_GO_FORWARD);
  g_signal_connect(G_OBJECT(btn), "clicked", G_CALLBACK(forward_image_browser), ui);
  gtk_box_pack_start(GTK_BOX(vhhbox), btn, FALSE, TRUE, 0);
  gtk_box_pack_end(GTK_BOX(vhbox), vhhbox, FALSE, TRUE, 12);
  gtk_box_pack_start(GTK_BOX(vbox), vhbox, FALSE, TRUE, 0);

  gtk_container_add(GTK_CONTAINER(ui->imagebrowser), vbox);
  g_signal_connect(G_OBJECT(ui->imagebrowser), "delete-event", G_CALLBACK(close_image_browser), ui);
  gtk_widget_show_all(ui->imagebrowser);
  gtk_widget_hide(ui->albums_page);
  gtk_widget_hide(ui->as_backbtn);
  gtk_widget_hide(ui->as_uploadbtn);
}

static gboolean close_upload_manager(GtkWidget *widget, GdkEvent *event, gpointer data) {
  pwa_uploader_ui_t *ui = (pwa_uploader_ui_t *)data;

  gtk_widget_destroy(ui->uploadmanager);
  ui->uploadmanager = NULL;
  return TRUE;
}

static void create_upload_manager(pwa_uploader_ui_t *ui) {
  GtkWidget *vbox = NULL, *vhbox = NULL, *vhhbox = NULL;
  GtkWidget *btn = NULL;

  ui->uploadmanager = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_window_set_title(GTK_WINDOW(ui->uploadmanager), "Upload Manager");
  gtk_window_set_modal(GTK_WINDOW(ui->uploadmanager), TRUE);
  gtk_window_set_position(GTK_WINDOW(ui->uploadmanager), GTK_WIN_POS_CENTER_ALWAYS);
  gtk_container_set_border_width(GTK_CONTAINER(ui->uploadmanager), 8);

  vbox = gtk_vbox_new(FALSE, 2);

  //gtk_box_pack_start(GTK_BOX(vbox), create_upload_manager_page(ui), TRUE, TRUE, 2);
  gtk_box_pack_start(GTK_BOX(vbox), gtk_hseparator_new(), FALSE, TRUE, 6);

  vhbox = gtk_hbox_new(FALSE, 0);
  vhhbox = gtk_hbox_new(TRUE, 8);
  btn = gtk_button_new_from_stock(GTK_STOCK_CLOSE);
  gtk_box_pack_start(GTK_BOX(vhhbox), btn, FALSE, TRUE, 0);
  gtk_box_pack_end(GTK_BOX(vhbox), vhhbox, FALSE, TRUE, 12);
  gtk_box_pack_start(GTK_BOX(vbox), vhbox, FALSE, TRUE, 0);

  gtk_container_add(GTK_CONTAINER(ui->uploadmanager), vbox);
  g_signal_connect(G_OBJECT(ui->uploadmanager), "delete-event", G_CALLBACK(close_upload_manager), ui);
  gtk_widget_show_all(ui->uploadmanager);
}

static void login_window_chkbtn_cb(GtkToggleButton *togglebutton, gpointer data) {
  pwa_uploader_ui_t *ui = (pwa_uploader_ui_t *)data;

  if(ui->rpchkbtn == GTK_WIDGET(togglebutton)) {
    DD("remember password is checked\n");
  } else if(ui->alchkbtn == GTK_WIDGET(togglebutton)) {
    if(gtk_toggle_button_get_active(togglebutton)) {
      gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ui->rpchkbtn), TRUE);
      gtk_widget_set_sensitive(ui->rpchkbtn, FALSE);
    } else {
      gtk_widget_set_sensitive(ui->rpchkbtn, TRUE);
    }
    DD("automatic login is checked\n");
  }
}

static void pwa_captcha_fetch_cb(SoupSession *session, SoupMessage *msg, gpointer data) {
  GdkPixbufLoader *pl = NULL;
  pwa_account_t *account = (pwa_account_t *)data;

  DD("captcha data len = %d\n\n",  msg->response_body->length);
  pl = gdk_pixbuf_loader_new();
  gdk_pixbuf_loader_write(pl, msg->response_body->data, msg->response_body->length, NULL);
  g_file_set_contents("captcha.jpg",  msg->response_body->data, msg->response_body->length, NULL);
  account->captcha_pixbuf = gdk_pixbuf_loader_get_pixbuf(pl);
  g_object_ref(account->captcha_pixbuf);
  gdk_pixbuf_loader_close(pl, NULL);
  account->sta = PWA_UPLOADER_STA_GOTCAPTCHA;

  g_signal_emit_by_name(account->ui->icon, "activate", G_TYPE_NONE, NULL);
}

static void pwa_captcha_pixbuf_fetch(pwa_account_t *account, gchar *captcha_url) {
  SoupMessage *msg = NULL;
  gchar *body = NULL;
  gchar url[1024] = {0};

  g_snprintf(url, 1024, GOOGLE_ACCOUNT_URL"%s", captcha_url);
  msg = soup_message_new("GET", url);
  soup_message_set_request(msg, NULL, SOUP_MEMORY_TAKE, NULL, 0);
  soup_session_queue_message(account->session, msg, pwa_captcha_fetch_cb, account);
}

static void pwa_login_cb(SoupSession *session, SoupMessage *msg, gpointer data) {
  GKeyFile *kf = NULL;
  gchar *auth_token;
  gchar *body = NULL;
  gint len = msg->response_body->length+strlen(MYGROUP) + 3;
  pwa_account_t *account = (pwa_account_t *)data;

  DD("PWA login status = %d, len = %d\n", msg->status_code, len);

  kf = g_key_file_new();
  body = g_malloc0(len);
  if(msg->response_body) {
    g_snprintf(body, len, "["MYGROUP"]\n%s", msg->response_body->data);
    g_key_file_load_from_data(kf, body, len, G_KEY_FILE_NONE, NULL);
  }

  if(msg->status_code == 200) {
    auth_token = g_key_file_get_value(kf, MYGROUP, "Auth", NULL);
    DD("token = %s\n", auth_token);
    account->sta = PWA_UPLOADER_STA_LOGINOK;
    account->token = g_strdup(auth_token);
    pwa_fetch_albums(account);
  } else {
    gchar *error = NULL;

    error = g_key_file_get_value(kf, MYGROUP, "Error", NULL);
    account->error = g_strdup(error);
    if(strcmp(error, "CaptchaRequired") == 0) {
      gchar *url = NULL, *captcha_token = NULL, *captcha_url = NULL;
      url = g_key_file_get_value(kf, MYGROUP, "Url", NULL);
      captcha_token = g_key_file_get_value(kf, MYGROUP, "CaptchaToken", NULL);
      captcha_url = g_key_file_get_value(kf, MYGROUP, "CaptchaUrl", NULL);
      //account->captcha_url = g_strdup_printf(GOOGLE_ACCOUNT_URL"%s", captcha_url);
      account->captcha_token = g_strdup(captcha_token);
      //DD("captcha_url = %s\n", account->captcha_url);
      pwa_captcha_pixbuf_fetch(account, captcha_url);
      account->sta = PWA_UPLOADER_STA_CAPTCHAREQUIRED;
    } else {
      account->sta = PWA_UPLOADER_STA_LOGINERR;
    }
  }
  g_free(body);
  g_key_file_free(kf);
  EF;

  g_signal_emit_by_name(account->ui->icon, "activate", G_TYPE_NONE, NULL);
}

static void XMLCALL elem_body_cb(void *data, const XML_Char *s, int len) {
  if(curr_album) {
    if(strcmp(curr_name, "gphoto:id") == 0) {
      curr_album->id = g_strndup(s, len);
    } else if(strcmp(curr_name, "gphoto:name") == 0) {
      curr_album->name = g_strndup(s, len);
    } else if(strcmp(curr_name, "gphoto:location") == 0) {
      curr_album->address = g_strndup(s, len);
    } else if(strcmp(curr_name, "gphoto:timestamp") == 0) {
      curr_album->date = g_strndup(s, len-3);
    } else if(strcmp(curr_name, "gphoto:numphotos") == 0) {
      curr_album->numphotos = g_strndup(s, len);
    } else if(strcmp(curr_name, "media:title") == 0) {
      curr_album->title = g_strndup(s, len);
      DD("new photo album %s\n", curr_album->title);
    } else if(strcmp(curr_name, "media:description") == 0) {
      curr_album->description = g_strndup(s, len);
    } else if(strcmp(curr_name, "gphoto:access") == 0) {
      curr_album->access = g_strndup(s, len);
    }
  }
}

static void XMLCALL elem_start_cb(void *data, const char *name, const char **atts) {
  curr_name = name;
  if(strcmp(name, "gphoto:id") == 0) {
    pwa_account_t *account = (pwa_account_t *)data;
    pwa_album_t *album = g_new0(pwa_album_t, 1);

    account->albums = g_slist_append(account->albums, album);
    curr_album = album;
  }
}

static void XMLCALL elem_end_cb(void *data, const char *name) {
  if(curr_album) {
    if(strcmp(curr_name, "media:title") == 0) {
      pwa_account_t *account = (pwa_account_t *)data;
      GtkTreeIter iter;

      gtk_tree_store_append(GTK_TREE_STORE(account->model), &iter, NULL);
      gtk_tree_store_set(GTK_TREE_STORE(account->model), &iter, PWA_TITLE_COL, curr_album->title, PWA_ALBUM_COL, curr_album, -1);
    }
  }
}

static void pwa_upload_photo_cb(SoupSession *session, SoupMessage *msg, gpointer data) {
  pwa_account_t *account = (pwa_account_t *)data;
  pwa_album_t *album = NULL;
  GSList *ptr = NULL;

  DD("upload photo status = %d\n", msg->status_code);
}

static void pwa_create_albums_cb(SoupSession *session, SoupMessage *msg, gpointer data) {
  pwa_account_t *account = (pwa_account_t *)data;
  pwa_album_t *album = NULL;
  GSList *ptr = NULL;
  GtkTreeIter iter;

  if(msg->response_body) {
    //DD("albums data = %s\n", msg->response_body->data);
    XML_Parse(account->ca_parser, msg->response_body->data, strlen(msg->response_body->data), TRUE);
  } else
    DD("fetch albums status = %d\n", msg->status_code);

  if(curr_album) {
    DD("append created page to treemodel\n");
    gtk_tree_store_append(GTK_TREE_STORE(account->model), &iter, NULL);
    gtk_tree_store_set(GTK_TREE_STORE(account->model), &iter, PWA_TITLE_COL, curr_album->title, PWA_ALBUM_COL, curr_album, -1);
  }

  XML_ParserFree(account->ca_parser);
#if 0

  for(ptr = account->albums; ptr != NULL; ptr = g_slist_next(ptr)) {
    album = ptr->data;
    DD("append to tree store title = %s\n", album->title);
    gtk_tree_store_append(GTK_TREE_STORE(account->model), &iter, NULL);
    gtk_tree_store_set(GTK_TREE_STORE(account->model), &iter, PWA_TITLE_COL, album->title, PWA_ALBUM_COL, album, -1);
    //gtk_combo_box_append_text(GTK_COMBO_BOX(ui->as_albums), album->title);
  }
#endif
}

static void pwa_fetch_albums_cb(SoupSession *session, SoupMessage *msg, gpointer data) {
  pwa_account_t *account = (pwa_account_t *)data;
  pwa_album_t *album = NULL;
  GSList *ptr = NULL;
  GtkTreeIter iter;

  if(msg->response_body) {
    //DD("albums data = %s\n", msg->response_body->data);
    XML_Parse(account->parser, msg->response_body->data, strlen(msg->response_body->data), TRUE);
  } else
    DD("fetch albums status = %d\n", msg->status_code);

  for(ptr = account->albums; ptr != NULL; ptr = g_slist_next(ptr)) {
    album = ptr->data;
    DD("append to tree store title = %s\n", album->title);
    gtk_tree_store_append(GTK_TREE_STORE(account->model), &iter, NULL);
    gtk_tree_store_set(GTK_TREE_STORE(account->model), &iter, PWA_TITLE_COL, album->title, PWA_ALBUM_COL, album, -1);
    //gtk_combo_box_append_text(GTK_COMBO_BOX(ui->as_albums), album->title);
  }
}

static void pwa_fetch_albums(pwa_account_t *account) {
  gchar url[1024] = {0};
  GSList *ptr = NULL;

  account->parser = XML_ParserCreate(NULL);
  XML_SetCharacterDataHandler(account->parser, elem_body_cb);
  XML_SetElementHandler(account->parser, elem_start_cb, NULL);
  XML_SetUserData(account->parser, account);
  
  if(account->token) {
    gchar val[1024] = {0};
    gchar *ptr = NULL;
    gint status;
    SoupMessage *msg = NULL;

    snprintf(url, 1024, PWA_DATA_URL"%s", account->username);
    ptr = strchr(url, '@');
    if(ptr) *ptr = '\0';
    DD("fetch albums url = %s\n", url);

    msg = soup_message_new("GET", url);
    g_snprintf(val, 1024, "GoogleLogin auth=%s", account->token);
    soup_message_headers_append(msg->request_headers, "Authorization", val);
    soup_session_queue_message(account->session, msg, pwa_fetch_albums_cb, account);
#if 0
    status = soup_session_send_message(account->session, msg);
    if(msg->response_body) {
      XML_Parse(parser, msg->response_body->data, strlen(msg->response_body->data), TRUE);
    } else
      DD("status = %d, resp = NULL\n", status);
#endif
  }
  EF;
}

void my_test_cb(SoupMessage *msg, SoupBuffer *chunk, gpointer data) {
  DD("wrote-body-data event, len = %d\n", chunk->length);
}

static void pwa_upload_photo(pwa_account_t *account, pwa_album_t *album, gchar *file) {
  gchar url[1024] = {0}, sizebuf[32] = {0}, val[128] = {0};
  SoupMultipart *multipart = NULL;
  gchar *body = NULL, *metadata = NULL;
  SoupMessage *msg = NULL;
  gint size;
  SoupMessageHeaders *header = NULL;
  SoupBuffer *buffer = NULL;
  gchar *title = "Demo.jpg", *summary = "This is a demo of PWA-Uploader";

  snprintf(url, 1024, PWA_DATA_URL"%s/albumid/%s", account->username, album->id);
  g_file_get_contents(file, &body, &size, NULL);
  snprintf(sizebuf, 32, "%d", size);

  metadata = g_strdup_printf("<entry xmlns='http://www.w3.org/2005/Atom'><title>%s</title><summary>%s</summary><category scheme=\"http://schemas.google.com/g/2005#kind\" term=\"http://schemas.google.com/photos/2007#photo\"/></entry>", title, summary);
  multipart = soup_multipart_new ("multipart/related");
  {
    header = soup_message_headers_new(SOUP_MESSAGE_HEADERS_MULTIPART);
    soup_message_headers_append(header, "Content-Type", "application/atom+xml");
    buffer = soup_buffer_new (SOUP_MEMORY_TAKE, metadata, strlen(metadata));
    soup_multipart_append_part(multipart, header, buffer);
    //soup_buffer_free(buffer);
    //soup_message_headers_free(header);
  }
  {
    header = soup_message_headers_new(SOUP_MESSAGE_HEADERS_MULTIPART);
    soup_message_headers_append(header, "Content-Type", "image/jpeg");
    buffer = soup_buffer_new (SOUP_MEMORY_TAKE, body, size);
    soup_multipart_append_part(multipart, header, buffer);
    //soup_buffer_free(buffer);
    //soup_message_headers_free(header);
  }

  DD("POST PHOTO: url = %s\n", url);
  msg = soup_form_request_new_from_multipart (url, multipart);
  g_signal_connect(msg, "wrote-body-data", G_CALLBACK(my_test_cb), NULL);
  g_snprintf(val, 1024, "GoogleLogin auth=%s", account->token);
  soup_message_headers_append(msg->request_headers, "Authorization", val);
  soup_message_headers_append(msg->request_headers, "MIME-version", "1.0");
  //soup_message_headers_replace(msg->request_headers, "Content-Type", "multipart/related; boundary=\"END_OF_PART\"");
  DD("post url = %s, size = %d, content-type=%s\n", url, size, soup_message_headers_get_one(msg->request_headers, "Content-Type"));

  soup_session_queue_message(account->session, msg, pwa_upload_photo_cb, account);
}

static void pwa_create_album(pwa_account_t *account, gchar *title, gchar *description, gchar *address, gchar *access) {
  gchar *body = NULL, *ptr = NULL;
  gchar url[1024] = {0}, val[1024] = {0};
  SoupMessage *msg = NULL;
  pwa_album_t *album = NULL;
  GSList *hdr = NULL;
  GtkTreeIter iter;
  XML_Parser parser;

  body = g_strdup_printf("<entry xmlns='http://www.w3.org/2005/Atom' xmlns:media='http://search.yahoo.com/mrss/' xmlns:gphoto='http://schemas.google.com/photos/2007'> <title type='text'>%s</title><summary type='text'>%s</summary><gphoto:location>%s</gphoto:location><gphoto:access>%s</gphoto:access><gphoto:commentingEnabled>true</gphoto:commentingEnabled><gphoto:timestamp>%d000</gphoto:timestamp><category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/photos/2007#album'></category></entry>", title, description, address, access, time(NULL));

  snprintf(url, 1024, PWA_DATA_URL"%s", account->username);
  ptr = strchr(url, '@');
  if(ptr) *ptr = '\0';

  account->ca_parser = parser = XML_ParserCreate(NULL);
  XML_SetCharacterDataHandler(parser, elem_body_cb);
  XML_SetElementHandler(parser, elem_start_cb, NULL);
  XML_SetUserData(parser, account);

  DD("****create new album URL %s****\n", url);
  msg = soup_message_new("POST", url);
  g_snprintf(val, 1024, "GoogleLogin auth=%s", account->token);
  soup_message_headers_append(msg->request_headers, "Authorization", val);
  soup_message_set_request(msg, "application/atom+xml", SOUP_MEMORY_TAKE, body, strlen(body));
  soup_session_queue_message(account->session, msg, pwa_create_albums_cb, account);
  //soup_session_send_message(account->session, msg);

  //DD("albums data = %s\n", msg->response_body->data);


}

static void pwa_account_login(pwa_account_t *account, gchar *captcha_text) {
  SoupMessage *msg = NULL;
  gchar *body = NULL;

  if(captcha_text) {
    if(strchr(account->username, '@'))
      body = g_strdup_printf("logintoken=%s&logincaptcha=%s&accountType=HOSTED_OR_GOOGLE&Email=%s&Passwd=%s&service=lh2&source="PWA_UPLOADER_AGENT, account->captcha_token, captcha_text, account->username, account->password);
    else
      body = g_strdup_printf("logintoken=%s&logincaptcha=%s&accountType=HOSTED_OR_GOOGLE&Email=%s@gmail.com&Passwd=%s&service=lh2&source="PWA_UPLOADER_AGENT, account->captcha_token, captcha_text, account->username, account->password);
    g_free(captcha_text);
  } else {
    if(strchr(account->username, '@'))
      body = g_strdup_printf("accountType=HOSTED_OR_GOOGLE&Email=%s&Passwd=%s&service=lh2&source="PWA_UPLOADER_AGENT, account->username, account->password);
    else
      body = g_strdup_printf("accountType=HOSTED_OR_GOOGLE&Email=%s@gmail.com&Passwd=%s&service=lh2&source="PWA_UPLOADER_AGENT, account->username, account->password);
  }
  DD("login message body\n %s\n", body);
  msg = soup_message_new("POST", PICASA_AUTH_URL);
  soup_message_set_request(msg, PICASA_AUTH_MIMETYPE, SOUP_MEMORY_TAKE, body, strlen(body));
  soup_session_queue_message(account->session, msg, pwa_login_cb, account);
}

static void create_login_dialog(pwa_uploader_ui_t *ui) {
  GtkWidget *dialog = NULL;
  GtkWidget *vbox = NULL, *vvbox = NULL, *logo = NULL, *vhbox = NULL, *vhvbox = NULL, *vvhbox = NULL;
  GtkWidget *chkbtn = NULL, *username = NULL, *password = NULL, *area = NULL, *label = NULL, *captcha_entry = NULL;

  ui->logindlg = dialog = gtk_dialog_new_with_buttons("Login Picasa Web Albums", NULL, GTK_DIALOG_MODAL,
                                       GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, 
                                       GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, NULL);
  gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_CENTER_ALWAYS);
  vbox = gtk_vbox_new(FALSE, 2);
  vhbox = gtk_hbox_new(FALSE, 0);
  logo = gtk_image_new_from_file(PWA_UPLOADER_DATA_PATH"/icon-64x64.png");
  gtk_box_pack_start(GTK_BOX(vhbox), logo, FALSE, TRUE, 8);
  label = gtk_label_new("");
  gtk_label_set_markup(GTK_LABEL(label), "<b>Picasa Web Albums</b>");
  gtk_box_pack_start(GTK_BOX(vhbox), label, TRUE, TRUE, 8);
  gtk_box_pack_start(GTK_BOX(vbox), vhbox, FALSE, TRUE, 0);

  vhbox = gtk_hbox_new(FALSE, 0);
  vhvbox = gtk_vbox_new(TRUE, 6);
  gtk_box_pack_start(GTK_BOX(vhvbox), gtk_label_new("Username:"), FALSE, TRUE, 0);
  gtk_box_pack_start(GTK_BOX(vhvbox), gtk_label_new("Password:"), FALSE, TRUE, 0);
  gtk_box_pack_start(GTK_BOX(vhbox), vhvbox, FALSE, TRUE, 8);

  vhvbox = gtk_vbox_new(TRUE, 6);
  username = gtk_entry_new();
  gtk_box_pack_start(GTK_BOX(vhvbox), username, FALSE, TRUE, 0);
  password = gtk_entry_new();
  gtk_entry_set_visibility(GTK_ENTRY(password), FALSE);
  gtk_box_pack_start(GTK_BOX(vhvbox), password, FALSE, TRUE, 0);
  gtk_box_pack_start(GTK_BOX(vhbox), vhvbox, TRUE, TRUE, 8);

  gtk_box_pack_start(GTK_BOX(vbox), vhbox, TRUE, TRUE, 10);

  vvbox = gtk_vbox_new(FALSE, 0);
  vvhbox = gtk_hbox_new(FALSE, 0);
  ui->rpchkbtn = chkbtn = gtk_check_button_new_with_label("Remember your password");
  g_signal_connect(chkbtn, "toggled", G_CALLBACK(login_window_chkbtn_cb), ui);
  gtk_box_pack_start(GTK_BOX(vvhbox), chkbtn, FALSE, TRUE, 8);
  gtk_box_pack_start(GTK_BOX(vvbox), vvhbox, TRUE, TRUE, 0);
  vvhbox = gtk_hbox_new(FALSE, 0);
  ui->alchkbtn = chkbtn = gtk_check_button_new_with_label("Automatic login");
  g_signal_connect(chkbtn, "toggled", G_CALLBACK(login_window_chkbtn_cb), ui);
  gtk_box_pack_start(GTK_BOX(vvhbox), chkbtn, FALSE, TRUE, 8);
  gtk_box_pack_start(GTK_BOX(vvbox), vvhbox, TRUE, TRUE, 0);

  gtk_box_pack_start(GTK_BOX(vbox), vvbox, FALSE, TRUE, 2);

  if(ui->account && ui->account->captcha_pixbuf) {
    GtkWidget *image = NULL;
    vvbox = gtk_vbox_new(FALSE, 6);
    image = gtk_image_new_from_pixbuf(ui->account->captcha_pixbuf);
    gtk_box_pack_start(GTK_BOX(vvbox), image, TRUE, TRUE, 0);
    captcha_entry = gtk_entry_new();
    gtk_box_pack_start(GTK_BOX(vvbox), captcha_entry, FALSE, TRUE, 0);
    gtk_box_pack_start(GTK_BOX(vbox), vvbox, FALSE, TRUE, 10);

    gtk_entry_set_text(GTK_ENTRY(username), ui->account->username);
    gtk_entry_set_text(GTK_ENTRY(password), ui->account->password);
    gtk_widget_set_sensitive(GTK_WIDGET(username), FALSE);
    gtk_widget_set_sensitive(GTK_WIDGET(password), FALSE);
    gtk_widget_set_sensitive(GTK_WIDGET(ui->rpchkbtn), FALSE);
    gtk_widget_set_sensitive(GTK_WIDGET(ui->alchkbtn), FALSE);
    gtk_entry_set_activates_default(GTK_ENTRY(captcha_entry), TRUE);
  } else {
    gtk_entry_set_activates_default(GTK_ENTRY(password), TRUE);
  }
  if(GTK_CHECK_VERSION(2, 14, 0))
    area = gtk_dialog_get_content_area(GTK_DIALOG (dialog));
  else
    area = GTK_DIALOG(dialog)->vbox;
  gtk_container_set_border_width(GTK_CONTAINER(area), 8);
  gtk_container_add (GTK_CONTAINER(area), vbox);

  gtk_widget_show_all(dialog);
  gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT);
  if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
    pwa_account_t *new_account = NULL;
    gchar *captcha_text = NULL;
    GtkTreeIter iter;

    if(ui->account) {
      new_account = ui->account;
      gtk_tree_store_clear(GTK_TREE_STORE(new_account->model));
    } else {
      new_account = g_new0(pwa_account_t, 1);
      new_account->session  = soup_session_sync_new_with_options(SOUP_SESSION_USER_AGENT, PWA_UPLOADER_AGENT, NULL);
      new_account->model = GTK_TREE_MODEL(gtk_tree_store_new(PWA_NUM_COL, G_TYPE_STRING, G_TYPE_POINTER));
    }
    gtk_tree_store_append(GTK_TREE_STORE(new_account->model), &iter, NULL);
    gtk_tree_store_set(GTK_TREE_STORE(new_account->model), &iter, PWA_TITLE_COL, "New Album", PWA_ALBUM_COL, NULL, -1);

    gtk_tree_store_append(GTK_TREE_STORE(new_account->model), &iter, NULL);
    gtk_tree_store_set(GTK_TREE_STORE(new_account->model), &iter, PWA_TITLE_COL, NULL, PWA_ALBUM_COL, NULL, -1);

    if(new_account->captcha_pixbuf) {
      captcha_text = g_strdup(gtk_entry_get_text(GTK_ENTRY(captcha_entry)));
      g_object_unref(new_account->captcha_pixbuf);
      new_account->captcha_pixbuf = NULL;
    } else {
      new_account->username = g_strdup(gtk_entry_get_text(GTK_ENTRY(username)));
      new_account->password = g_strdup(gtk_entry_get_text(GTK_ENTRY(password)));
      new_account->captcha_token = NULL;
    }

    //new_account->session  = soup_session_sync_new_with_options(SOUP_SESSION_USER_AGENT, PWA_UPLOADER_AGENT, NULL);
    new_account->ui       = ui;
    new_account->sta      = PWA_UPLOADER_STA_LOGIN;
    DD("New account: username = %s, password = %s\n", new_account->username, new_account->password);
    ui->account = new_account;

    pwa_account_login(new_account, captcha_text);
  }
  gtk_widget_destroy(dialog);
  ui->logindlg = NULL; 
}

static void tray_icon_activate(GtkStatusIcon *icon, gpointer data) {
  pwa_uploader_ui_t *ui = (pwa_uploader_ui_t *)data;

  if(ui->account) {
    gchar msg[1024] = {0};
    pwa_account_t *account = ui->account;
    switch(account->sta) {
      case PWA_UPLOADER_STA_0:
      if(!ui->logindlg) {
        create_login_dialog(ui);
      }
      break;

      case PWA_UPLOADER_STA_LOGIN:
      DD("login to picasa web albums, please waiting!\n");
      break;

      case PWA_UPLOADER_STA_LOGINOK:
      if(ui->notifydlg) {
        gtk_dialog_response(GTK_DIALOG(ui->notifydlg), GTK_RESPONSE_ACCEPT);
        break;
      }
      ui->notifydlg = gtk_message_dialog_new_with_markup(NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE, "<span foreground='#57a057' weight='bold' size='x-large'>%s</span> login success !\nNow you can upload photos to Picasa web albums.", ui->account->username);
      gtk_window_set_position(GTK_WINDOW(ui->notifydlg), GTK_WIN_POS_CENTER_ALWAYS);
      gtk_widget_show(ui->notifydlg);
      gtk_dialog_run(GTK_DIALOG(ui->notifydlg));
      gtk_widget_destroy(ui->notifydlg);
      ui->notifydlg = NULL;
      //pwa_create_album(ui->account, "PWA.uploader", "TEST album created by PWA-Uploader", "Hangzhou, Zhejiang", "public");
      break;
      case PWA_UPLOADER_STA_LOGINERR:
      if(ui->notifydlg) {
        gtk_dialog_response(GTK_DIALOG(ui->notifydlg), GTK_RESPONSE_ACCEPT);
        break;
      }
      ui->notifydlg = gtk_message_dialog_new_with_markup(NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "<span foreground='red' weight='bold' size='x-large'>%s</span> login failed!\nPlease check username and password again.\nerror = %s.", ui->account->username, ui->account->error);
      gtk_window_set_position(GTK_WINDOW(ui->notifydlg), GTK_WIN_POS_CENTER_ALWAYS);
      gtk_widget_show(ui->notifydlg);
      gtk_dialog_run(GTK_DIALOG(ui->notifydlg));
      gtk_widget_destroy(ui->notifydlg);
      ui->notifydlg = NULL;
      account->sta = PWA_UPLOADER_STA_0;
      break;
      case PWA_UPLOADER_STA_CAPTCHAREQUIRED:
      DD("captcha is required for login Picasa web albums!\n");
      break;
      case PWA_UPLOADER_STA_GOTCAPTCHA:
      create_login_dialog (ui);
      break;
    }
  } else {
    if(ui->logindlg==NULL && ui->account==NULL) {
      create_login_dialog(ui);
    }
  }
}

static void popmenu_login_activated (GtkCheckMenuItem *item, gpointer data) {
  pwa_uploader_ui_t *ui = (pwa_uploader_ui_t *)data;
  create_login_dialog(ui);
}

static void popmenu_logout_activated (GtkCheckMenuItem *item, gpointer data) {
  pwa_uploader_ui_t *ui = (pwa_uploader_ui_t *)data;

  if(ui->account) {
    if(ui->account->username)
      g_free(ui->account->username);
    if(ui->account->password)
      g_free(ui->account->password);
    if(ui->account->token)
      g_free(ui->account->token);
    if(ui->account->session)
      g_object_unref(ui->account->session);
    if(ui->account->parser)
      XML_ParserFree(ui->account->parser);

    g_free(ui->account);
  }
  ui->account = NULL;
}

static void popmenu_quit_activated (GtkCheckMenuItem *item, gpointer data) {
  pwa_uploader_ui_t *ui = (pwa_uploader_ui_t *)data;

  if(ui->aboutdlg) {
    gtk_dialog_response(GTK_DIALOG(ui->aboutdlg), GTK_RESPONSE_ACCEPT);
  }
  if(ui->logindlg) {
    gtk_dialog_response(GTK_DIALOG(ui->logindlg), GTK_RESPONSE_CANCEL);
  }

  gtk_main_quit();
}

static void popmenu_uploadmgr_activated (GtkCheckMenuItem *item, gpointer data) {
  pwa_uploader_ui_t *ui = (pwa_uploader_ui_t *)data;

}

static void popmenu_browser_activated (GtkCheckMenuItem *item, gpointer data) {
  pwa_uploader_ui_t *ui = (pwa_uploader_ui_t *)data;

  create_image_browser(ui);
}

static void popmenu_about_activated (GtkCheckMenuItem *item, gpointer data) {
  pwa_uploader_ui_t *ui = (pwa_uploader_ui_t *)data;
  GtkWidget *dialog = NULL;
  GdkPixbuf *logo = NULL;
  const gchar *authors[] = {
    "RuXu Wu - wrxzzj@gmail.com",
    NULL
  };
  const gchar *artists[] = {
    "RuXu Wu - wrxzzj@gmail.com",
    NULL
  };

  ui->aboutdlg = dialog = gtk_about_dialog_new();
  gtk_about_dialog_set_program_name(GTK_ABOUT_DIALOG(dialog), "Picasa Uploader");
  gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(dialog), "1.0beta");
  gtk_about_dialog_set_copyright(GTK_ABOUT_DIALOG(dialog), "Copyright 2009 by RuXu Wu");
  gtk_about_dialog_set_comments(GTK_ABOUT_DIALOG(dialog), "Picasa photos uploader tool for linux");
  gtk_about_dialog_set_license(GTK_ABOUT_DIALOG(dialog), "GPL v3");
  gtk_about_dialog_set_authors(GTK_ABOUT_DIALOG(dialog), authors);
  gtk_about_dialog_set_artists(GTK_ABOUT_DIALOG(dialog), artists);

  logo = gdk_pixbuf_new_from_file(PWA_UPLOADER_DATA_PATH"/about-logo.png", NULL);
  gtk_about_dialog_set_logo(GTK_ABOUT_DIALOG(dialog), logo);
  g_object_unref(logo);

  gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_CENTER_ALWAYS);
  gtk_widget_show(dialog);
  gtk_dialog_run(GTK_DIALOG(dialog));
  gtk_widget_destroy(dialog);
  ui->aboutdlg = NULL;
}

static void tray_icon_popmenu(GtkStatusIcon *icon, guint button, guint32 activate_time, gpointer data) {
  GtkWidget *menu, *menuitem;
  pwa_uploader_ui_t *ui = (pwa_uploader_ui_t *)data;
  pwa_account_t *account = ui->account;

  menu = gtk_menu_new();
  gtk_menu_set_screen(GTK_MENU (menu), gtk_status_icon_get_screen (icon));

  menuitem = gtk_image_menu_item_new_from_stock(GTK_STOCK_QUIT, NULL);
  g_signal_connect (menuitem, "activate", G_CALLBACK (popmenu_quit_activated), data);
  gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
  gtk_menu_shell_append (GTK_MENU_SHELL (menu), gtk_separator_menu_item_new());

  menuitem = gtk_image_menu_item_new_from_stock(GTK_STOCK_PREFERENCES, NULL);
  gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
  gtk_menu_shell_append (GTK_MENU_SHELL (menu), gtk_separator_menu_item_new());
  menuitem = gtk_image_menu_item_new_with_label ("Smart Browser");
  g_signal_connect (menuitem, "activate", G_CALLBACK (popmenu_browser_activated), data);
  gtk_widget_set_sensitive(GTK_WIDGET(menuitem), ui->imagebrowser == NULL);
  gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
  menuitem = gtk_image_menu_item_new_with_label ("Upload Manager");
  gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), gtk_image_new_from_stock(GTK_STOCK_GO_UP, GTK_ICON_SIZE_MENU));
  g_signal_connect (menuitem, "activate", G_CALLBACK (popmenu_uploadmgr_activated), data);
  gtk_widget_set_sensitive(GTK_WIDGET(menuitem), ui->uploadmanager== NULL);
  gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
  gtk_menu_shell_append (GTK_MENU_SHELL (menu), gtk_separator_menu_item_new());

  if(account && account->sta == PWA_UPLOADER_STA_LOGINOK) {
    GtkWidget *submenu = NULL, *submenuitem = NULL;
    submenu = gtk_menu_new();
    submenuitem = gtk_image_menu_item_new_with_label("Web Albums Browser");
    gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(submenuitem), gtk_image_new_from_stock(GTK_STOCK_HOME, GTK_ICON_SIZE_MENU));
    gtk_menu_shell_append (GTK_MENU_SHELL (submenu), submenuitem);
    gtk_menu_shell_append (GTK_MENU_SHELL (submenu), gtk_separator_menu_item_new());
    submenuitem = gtk_image_menu_item_new_with_label("Logout");
    gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(submenuitem), gtk_image_new_from_stock(GTK_STOCK_DISCONNECT, GTK_ICON_SIZE_MENU));
    g_signal_connect (submenuitem, "activate", G_CALLBACK (popmenu_logout_activated), data);
    gtk_menu_shell_append (GTK_MENU_SHELL (submenu), submenuitem);

    menuitem = gtk_menu_item_new_with_mnemonic(account->username);
    gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
  } else {
    menuitem = gtk_menu_item_new_with_mnemonic("Picasa Albums _Login");
    gtk_widget_set_sensitive(GTK_WIDGET(menuitem), ui->logindlg == NULL);
    g_signal_connect (menuitem, "activate", G_CALLBACK (popmenu_login_activated), data);
  }
  gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
  gtk_menu_shell_append (GTK_MENU_SHELL (menu), gtk_separator_menu_item_new());

  menuitem = gtk_image_menu_item_new_from_stock (GTK_STOCK_ABOUT, NULL);
  g_signal_connect (menuitem, "activate", G_CALLBACK (popmenu_about_activated), data);
  gtk_widget_set_sensitive(GTK_WIDGET(menuitem), ui->aboutdlg == NULL);
  gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);

  gtk_widget_show_all(menu);
  gtk_menu_popup (GTK_MENU (menu), NULL, NULL, gtk_status_icon_position_menu, icon, button, activate_time);
}

static pwa_uploader_ui_t *pwa_uploader_ui_alloc() {
  pwa_uploader_ui_t *ui= NULL;
  gchar cfgpath[1024] = {0};

  ui = g_new0(pwa_uploader_ui_t, 1);
  g_snprintf(cfgpath, 1024, "%s/"PWA_UPLOADER_CFG, getenv("HOME"));
  ui->kf = g_key_file_new();
  if(!g_key_file_load_from_file(ui->kf, cfgpath, G_KEY_FILE_NONE, NULL)) {
  }
  ui->icon = gtk_status_icon_new ();

  gtk_status_icon_set_screen (ui->icon, gdk_screen_get_default());
  gtk_status_icon_get_geometry(ui->icon, NULL, &ui->area, &ui->orientation);

  return ui;
}

static void pwa_uploader_ui_free(pwa_uploader_ui_t *ui) {
  if(ui->account) {
    if(ui->account->username)
      g_free(ui->account->username);
    if(ui->account->password)
      g_free(ui->account->password);
    if(ui->account->token)
      g_free(ui->account->token);
    if(ui->account->session);
      g_object_unref(ui->account->session);
    if(ui->account->parser)
      XML_ParserFree(ui->account->parser);
  }
  if(ui->kf) {
    g_key_file_free(ui->kf);
  }
  g_free(ui);
}

int main (int argc, char **argv) {
  pwa_uploader_ui_t *ui = NULL;

  g_thread_init (NULL);
  gtk_init (&argc, &argv);

  ui = pwa_uploader_ui_alloc();
  gtk_status_icon_set_blinking (ui->icon, FALSE);
  gtk_status_icon_set_from_file (ui->icon, PWA_UPLOADER_DATA_PATH"/icon-64x64.png");
  gtk_status_icon_set_tooltip (ui->icon, "Picasa Web Albums Uploader");

  g_signal_connect (ui->icon, "activate", G_CALLBACK(tray_icon_activate), ui);
  g_signal_connect (ui->icon, "popup-menu", G_CALLBACK(tray_icon_popmenu), ui);

  create_login_dialog(ui);

  gtk_main ();

  pwa_uploader_ui_free(ui);

  return 0;
}
